/*
 * @Author: shenghao.xu
 * @Date: 2023-04-11 16:06:04
 * @LastEditors: shenghao.xu
 * @LastEditTime: 2023-06-05 09:13:52
 * @Description: 串口驱动，支持多串口，使用中断方式接收数据
 * email:545403892@qq.com
 * Copyright (c) 2023 by shenghao.xu, All Rights Reserved.
 */

#include "uart.h"

static uart_t uart[UART_MAX];

void UartInit(uart_id_e id, UART_HandleTypeDef *huart, BOOL dma_rx_en, uint16_t rxsize, rx_interupt_cb_t rx_cb, BOOL dma_tx_en, uint16_t txsize)
{
    DBG_ASSERT(id < UART_MAX __DBG_LINE);
    DBG_ASSERT(huart != NULL __DBG_LINE);
    DBG_ASSERT(rx_cb != NULL __DBG_LINE);

    uart_t *handle = &uart[id];
    osel_memset((uint8_t *)handle, 0, sizeof(uart_t));

    handle->dma_rx_en = dma_rx_en;
    handle->rx_size = rxsize;
    if (rxsize > 0)
    {
        handle->rx_buffer = (uint8_t *)osel_mem_alloc(rxsize);
        DBG_ASSERT(handle->rx_buffer != NULL __DBG_LINE);
    }

    handle->dma_tx_en = dma_tx_en;
    handle->tx_size = txsize;
    if (txsize > 0)
    {
        handle->tx_buffer = (uint8_t *)osel_mem_alloc(txsize);
        DBG_ASSERT(handle->tx_buffer != NULL __DBG_LINE);
    }

    handle->rx_interupt_cb = rx_cb;
    handle->huart = huart;
    handle->id = id;
}

uart_t *UartGetHandle(uart_id_e id)
{
    DBG_ASSERT(id < UART_MAX __DBG_LINE);
    return &uart[id];
}

void UARTReceiveIT(uart_id_e id)
{
    uart_t *handle = &uart[id];
    DBG_ASSERT(handle->huart != NULL __DBG_LINE);
    if (handle->dma_rx_en)
    {
        // 开启串口DMA接收
        HAL_UARTEx_ReceiveToIdle_DMA(handle->huart, handle->rx_buffer, handle->rx_size);
    }
    else
    {
        HAL_UART_Receive_IT(handle->huart, handle->rx_buffer, handle->rx_size);
    }
}

void UartSend(uart_id_e id, uint8_t *data, uint16_t len)
{
    uart_t *handle = &uart[id];
    DBG_ASSERT(handle->huart != NULL __DBG_LINE);
    if (handle->dma_tx_en)
    {
        HAL_UART_Transmit_DMA(handle->huart, data, len);
    }
    else
    {
        HAL_UART_Transmit(handle->huart, data, len, 0xFFFF); /*发送接收到的数据*/
    }
    while (__HAL_UART_GET_FLAG(handle->huart, UART_FLAG_TC) != SET)
        ; /*等待发送结束*/
}

/**
 * @brief       接收完成中断的回调函数
 * @param       huart: UART句柄类型指针
 * @retval      无
 */
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
    uint32_t timeout = 0;
    uint32_t maxDelay = 0x1FFFF;
    for (uint8_t i = 0; i < UART_MAX; i++)
    {
        uart_t *handle = &uart[i];
        if (handle->huart->Instance == huart->Instance)
        {
            if (huart->ErrorCode & HAL_UART_ERROR_ORE)
            {
                __HAL_UART_CLEAR_OREFLAG(huart);
                while (HAL_UART_Receive_IT(handle->huart, handle->rx_buffer, handle->rx_size) != HAL_OK)
                {
                    timeout++; /* 超时处理 */
                    if (timeout > maxDelay)
                    {
                        DBG_ASSERT(FALSE __DBG_LINE);
                    }
                }
                break;
            }
            while (HAL_UART_GetState(handle->huart) != HAL_UART_STATE_READY) /* 等待就绪 */
            {
                timeout++; /* 超时处理 */
                if (timeout > maxDelay)
                {
                    break;
                }
            }

            timeout = 0;
            while (HAL_UART_Receive_IT(handle->huart, handle->rx_buffer, handle->rx_size) != HAL_OK)
            {
                timeout++; /* 超时处理 */
                if (timeout > maxDelay)
                {
                    break;
                }
            }

            if (handle->rx_interupt_cb != NULL)
            {
                handle->rx_interupt_cb(huart);
            }

            break;
        }
    }
}

/**
 * @brief       接收完成中断的回调函数
 * @param       huart: UART句柄类型指针
 * @retval      无
 */
void HAL_UARTEx_RxEventCallback(UART_HandleTypeDef *huart, uint16_t size)
{
    for (uint8_t i = 0; i < UART_MAX; i++)
    {
        uart_t *handle = &uart[i];
        if (handle != NULL)
        {
            if (handle->huart->Instance == huart->Instance)
            {
                handle->rxIndex = size; /*接收到的数据长度*/
                if (handle->rx_interupt_cb != NULL && size > 0)
                {
                    handle->rx_interupt_cb(huart);
                }
                UARTReceiveIT(handle->id);
                break;
            }
        }
    }
}

void HAL_UART_ErrorCallback(UART_HandleTypeDef *huart)
{
    if (huart->ErrorCode & HAL_UART_ERROR_ORE)
    {
        __HAL_UART_CLEAR_OREFLAG(huart);
    }
    __HAL_UNLOCK(huart);
    for (uint8_t i = 0; i < UART_MAX; i++)
    {
        uart_t *handle = &uart[i];
        if (handle->huart->Instance == huart->Instance)
        {
            UARTReceiveIT((uart_id_e)i);
            break;
        }
    }
}
